package edu.nf.project.services.other.impl;

import edu.nf.project.entitys.dto.storeOperation.DishCargo;
import edu.nf.project.entitys.dto.storeOperation.DishDTO;
import edu.nf.project.entitys.dto.storeOperation.SubmitOrderRequest;
import edu.nf.project.entitys.dto.storeOperation.SubmitOrderResult;
import edu.nf.project.entitys.entity.storeOperation.convention.cargo.Cargo;
import edu.nf.project.entitys.entity.storeOperation.convention.dish.Dish;
import edu.nf.project.entitys.enums.storeOperation.InventoryLock;
import edu.nf.project.mappers.storeOperation.convention.*;
import edu.nf.project.services.other.InventoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @Author gjh
 * @Date 2025/6/20
 * @Description:
 */
@Service
public class InventoryServiceImpl implements InventoryService {

    @Autowired
    private DishDTOMapper dishDTOMapper;
    @Autowired
    private DishCargoMapper dishCargoMapper;
    @Autowired
    private CargoMapper cargoMapper;
    @Autowired
    private InventoryLockMapper inventoryLockMapper;

    @Override
    public SubmitOrderResult checkAndLockInventory(SubmitOrderRequest request) {
        List<Integer> dishIds = request.getDishIdList();
        Long orderId = request.getOrderId();

        // 1. 查出所有 dish，包含优先级
        List<DishDTO> dishList = dishDTOMapper.selectBatchByIds(dishIds);
        dishList.sort(Comparator.comparing(DishDTO::getPriority)); // 按优先级升序

        // 2. 查询 dish_cargo 中涉及的食材
        List<DishCargo> allIngredients = dishCargoMapper.selectByDishIds(dishIds);

        // 3. 构建菜品与食材映射
        Map<Integer, List<DishCargo>> dishToIngredients = new HashMap<>();
        Set<Integer> cargoIds = new HashSet<>();

        for (DishCargo dc : allIngredients) {
            dishToIngredients.computeIfAbsent(dc.getDishId(), k -> new ArrayList<>()).add(dc);
            cargoIds.add(dc.getCargoId());
        }

        // 4. 查询 cargo 表中的库存
        List<Cargo> cargoList = cargoMapper.selectByIds(new ArrayList<>(cargoIds));
        Map<Integer, Integer> stockMap = new HashMap<>();
        for (Cargo c : cargoList) {
            stockMap.put(c.getCargoId(), c.getStockQuantity());
        }

        // 5. 虚拟扣库存
        List<Integer> canMake = new ArrayList<>();
        List<String> cannotMake = new ArrayList<>();

        for (DishDTO dish : dishList) {
            boolean ok = true;
            for (DishCargo dc : dishToIngredients.getOrDefault(dish.getDishId(), List.of())) {
                int available = stockMap.getOrDefault(dc.getCargoId(), 0);
                if (available < dc.getQuantityNeeded()) {
                    ok = false;
                    break;
                }
            }

            if (ok) {
                canMake.add(dish.getDishId());
                // 扣掉虚拟库存
                for (DishCargo dc : dishToIngredients.get(dish.getDishId())) {
                    stockMap.put(dc.getCargoId(), stockMap.get(dc.getCargoId()) - dc.getQuantityNeeded());

                    // 插入 inventory_lock 表
                    InventoryLock lock = new InventoryLock();
                    lock.setOrderId(orderId);
                    lock.setCargoId(dc.getCargoId());
                    lock.setQuantity(dc.getQuantityNeeded());
                    lock.setStatus("LOCKED");
                    inventoryLockMapper.insert(lock);
                }
            } else {
                cannotMake.add(dish.getDishName());
            }
        }

        SubmitOrderResult result = new SubmitOrderResult();
        result.setCanMakeDishIds(canMake);
        result.setCannotMakeDishNames(cannotMake);
        return result;
    }

    @Override
    public void confirmInventory(Long orderId) {
        // 1. 查找该订单所有 LOCKED 状态的库存记录
        List<InventoryLock> lockedList = inventoryLockMapper.findLockedByOrderId(orderId);

        for (InventoryLock lock : lockedList) {
            // 2. 扣减 cargo 表中库存
            cargoMapper.decreaseStock(lock.getCargoId(), lock.getQuantity());

            // 3. 更新 inventory_lock 状态为 DEDUCTED
            inventoryLockMapper.updateStatus(lock.getId(), "DEDUCTED");
        }
    }
}
